package org.goldenport.g3

import scala.collection.mutable.ArrayBuffer
import scala.tools.nsc.{ScriptRunner, GenericRunnerSettings, Interpreter}
import scala.tools.nsc.util.BatchSourceFile
import scala.io.Source
import org.goldenport.Goldenport
import org.goldenport.parameter.GParameterRepository
import org.goldenport.service._
import org.goldenport.entity._
import org.goldenport.entities.csv.CsvEntity
import org.goldenport.entities.xmind.XMindEntity
import org.goldenport.g3.events.Getted

/*
 * @since   May.  8, 2010
 * @version Nov. 10, 2011
 * @author  ASAMI, Tomoharu
 */
class G3Service(aCall: GServiceCall, serviceClass: GServiceClass) extends GService(aCall, serviceClass) {
  def execute_Service(aRequest: GServiceRequest, aResponse: GServiceResponse) {
    val parameters = aRequest.parameters
    val g3AppName = parameters.get("g3.application") orElse
                    parameters.get("g3.app") orElse
                    parameters.get("app") match {
      case Some(name) => name.toString
      case None => "App"
    }

    val gcontext = call.serviceContext

    val settings = new GenericRunnerSettings((error: String) => println(error))
//    val ps = settings.processArguments(args, true)._2 XXX
    settings.usejavacp.value = true
    settings.nocompdaemon.value = true // XXX
    val ip = new Interpreter(settings)

    def execute_init_script {
      parameters.get("g3.script") collect {
        case filename: String => {
          val src = Source.fromFile(filename, "utf-8")
          for (line <- src.getLines) {
            ip.interpret(line)
          }
        }
      }
    }

    def find_application_script: Option[G3Application] = {
      parameters.get("g3.script.app") collect {
        case filename: String => {
          val file = new scala.tools.nsc.io.PlainFile(scala.tools.nsc.io.File(new java.io.File(filename)))
          ip.compileSources(new BatchSourceFile(file))
          val cl = ip.classLoader
          val klass = cl.loadClass(g3AppName)
          klass.newInstance.asInstanceOf[G3Application]
        }
      }
    }

    def find_application_goldenport: G3Application = {
      try {
        gcontext.newInstance(g3AppName)
      } catch {
        case e: Exception => {
          record_error(e, "Unavailable application = " + g3AppName)
          new G3Application()
        }
      }
    }

    def find_application = {
      find_application_script.getOrElse(find_application_goldenport)
    }

    execute_init_script

    val app = find_application
//    aRequest.entity
    app.open(parameters, call.session, call.serviceContext, ip)
    val result = app.run(aRequest.arguments.map(_.asInstanceOf[AnyRef]).toArray: _*)
//    println("G3Service: " + result + "/" + result.asInstanceOf[AnyRef].getClass)
/*
    val result = app.run(aRequest.arguments.toArray: _*) match {
      case get: Getted => {
        get.contents.length match {
          case 0 => None
          case 1 => Some(get.contents(0))
          case _ => Some(get.contents)
        }
      }
      case Some(r) => Some(r)
      case None => None
      case r => Some(r)
    }
*/
    app.close()
    if (!is_no_result(result)) {
      aResponse.setResult(result)
    }
//    aResponse.addRealm(projectRealm)
  }

  private def is_no_result(result: Any) = {
    result == Nil || result == None
  }
}

object G3Service extends GServiceClass("g3") {
  def new_Service(aCall: GServiceCall): GService =
    new G3Service(aCall, this)
}
